package com.taiic.fourcamera;

import android.Manifest;
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.herohan.uvcapp.CameraException;
import com.herohan.uvcapp.CameraHelper;
import com.herohan.uvcapp.ICameraHelper;
import com.hjq.permissions.XXPermissions;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.UVCCamera;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

public class UsbCamerManager {

    public enum DataType {
        NV12,
        YUYV,
        GRAY
    }

    public enum CameraType {
        FISHEYE, //鱼眼相机
        EYE_WIDE //眼图相机
    }

    private static final boolean DEBUG = true;
    private static final String TAG = "taiic_UsbCamerManager";
    //    设置相机参数
    private final int mWidth = 640;
    private final int mHeight = 240;
    private final int mFps = 30;
    private final int mType = 5;
    private final List<Integer> mFpsList = Arrays.asList(30);
    private final int mNV12Length = mWidth * mHeight * 3 / 2; //nv12
    private final int mYLength = mWidth * mHeight; //y
    private byte[] nv12Byte = new byte[mNV12Length];
    private byte[] yByte = new byte[mYLength];

    private ICameraHelper mCameraHelper;// usb camera管理接口
    private final CopyOnWriteArrayList<IUsbCamera> mCallbacks = new CopyOnWriteArrayList<>();
    private UsbDevice mUsbDevice;
    private AtomicBoolean mIsCameraConnected = new AtomicBoolean(false); // 使用 AtomicBoolean 进行原子操作
    private Context mContext;

    private AtomicBoolean isFirstCall = new AtomicBoolean(true);
    private final ExecutorService executorService = Executors.newFixedThreadPool(2);
    private int dataCont = 0;

    //    1. 静态内部类，只有在调用 getInstance 时才会加载
    private static class UsbCamerManagerHolder {
        private static final UsbCamerManager INSTANCE = new UsbCamerManager();
    }

    //    2. 私有的构造方法，防止外部直接实例化
    private UsbCamerManager() {
    }

    //    3. 公共的静态方法，用于获取唯一实例,线程安全的单例模式,静态内部类实现
    public static UsbCamerManager getInstance() {
        return UsbCamerManagerHolder.INSTANCE;
    }

    private final ICameraHelper.StateCallback mStateListener = new ICameraHelper.StateCallback() {
        @Override
        public void onAttach(UsbDevice device) {
            // 摄像头连接时的回调
            if (DEBUG)
                Log.v(TAG, "onAttach: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            attachNewDevice(device);
        }

        @Override
        public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) {
            if (DEBUG)
                Log.v(TAG, "onDeviceOpen: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            mCameraHelper.openCamera();
        }

        @Override
        public void onCameraOpen(UsbDevice device) {
            // 摄像头打开时的回调
            if (DEBUG)
                Log.v(TAG, "onCameraOpen: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            Size size = mCameraHelper.getPreviewSize();
            size.width = mWidth;
            size.height = mHeight;
            size.fps = mFps;
            size.type = mType;
            size.fpsList = mFpsList;
            mCameraHelper.setPreviewSize(size);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mCameraHelper.startPreview();
            setCameraConnected(true);
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    mCameraHelper.setFrameCallback(frame -> {
//                        Log.d(TAG, "Frame received: size" + frame.remaining());
                        if (frame == null) {
                            Log.w(TAG, "Frame is null, skipping frame");
                            return;
                        }
                        // 确保 yBytes 的大小足够
                        if (nv12Byte == null || nv12Byte.length < frame.remaining()) {
                            Log.w(TAG, "nv12Byte is null or length is no enough");
                            nv12Byte = new byte[frame.remaining()];
                        }
                        dataCont++;
                        try {
                            if (dataCont % 2 == 0) {
                                dataCont = 0;
//                            Log.d(TAG, "frame.remaining: size = " + frame.remaining());
                                executorService.submit(() -> {
//                                    Log.d(TAG, "34345frame.remaining: size = " + frame.remaining());
                                    frame.get(nv12Byte, 0, frame.remaining());
                                    System.arraycopy(nv12Byte, 0, yByte, 0, mYLength);
                                    notifyFrame(yByte, mWidth, mHeight, DataType.GRAY, CameraType.EYE_WIDE);
                                });
                            }
                        } catch (Exception e) {
                            Log.e("CameraHelper", "Error while reading frame data", e);
                        }
                    }, UVCCamera.PIXEL_FORMAT_NV12);
                }
            }, 4000); // 延迟 4 秒
        }

        @Override
        public void onCameraClose(UsbDevice device) {
            if (DEBUG)
                Log.v(TAG, "onCameraClose: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            setCameraConnected(false);
//            mCameraHelper.setFrameCallback(null, UVCCamera.PIXEL_FORMAT_NV12);
        }

        @Override
        public void onDeviceClose(UsbDevice device) {
            if (DEBUG)
                Log.v(TAG, "onDeviceClose: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
        }

        @Override
        public void onDetach(UsbDevice device) {
            if (DEBUG)
                Log.v(TAG, "onDetach: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            if (device.equals(mUsbDevice)) {
                mUsbDevice = null;
            }
        }

        @Override
        public void onCancel(UsbDevice device) {
            if (DEBUG)
                Log.v(TAG, "onCancel: " + "Current line: " + Thread.currentThread().getStackTrace()[2].getLineNumber());
            if (device.equals(mUsbDevice)) {
                mUsbDevice = null;
            }
        }

        @Override
        public void onError(UsbDevice device, CameraException e) {
            // 摄像头错误时的回调
            Log.e(TAG, "onError: " + e.toString());

        }
    };

    private void attachNewDevice(UsbDevice device) {
        Log.d(TAG, "device_info: devicename:[" + device.getDeviceName() + "]," +
                "devicedeviceid:[" + device.getDeviceId() + "]," +
                "deviceProductName:[" + device.getProductName() + "]," +
                "deviceVendorId:[" + device.getVendorId() + "]," +
                "deviceSerialNumber:[" + device.getSerialNumber() + "]," +
                "getProductId:[" + device.getProductId() + "]");

        if (mUsbDevice == null && device.getProductId() == 65052) {
            mUsbDevice = device;
            selectDevice(device);
        }
    }

    private void selectDevice(UsbDevice device) {
        if (DEBUG) Log.v(TAG, "selectDevice:device=" + device.getDeviceName());
        XXPermissions.with(mContext)
                .permission(Manifest.permission.CAMERA)
                .request((permissions, all) -> {
                    setCameraConnected(false);
                    if (mCameraHelper != null) {
                        // 通过UsbDevice对象，尝试获取设备权限
                        mCameraHelper.selectDevice(device);
                    }
                });
    }

    private void clearCameraHelper() {
        if (DEBUG) Log.v(TAG, "clearCameraHelper:");
        if (mCameraHelper != null) {
            mCameraHelper.release();
            mCameraHelper = null;
        }
    }

    private void clearAllCallback() {
        mCallbacks.clear();
        if (DEBUG) Log.d(TAG, "clearAllCallback: ");
    }

    private void notifyFrame(byte[] data, int width, int height, DataType dataType, CameraType cameraType) {
        for (IUsbCamera callback : mCallbacks) {
            try {
                callback.onFrame(data, width, height, dataType, cameraType);
            } catch (Exception e) {
                Log.e(TAG, "notifyFrame: ", e);
            }
        }
    }

    // 设置摄像头连接状态
    private void setCameraConnected(boolean connected) {
        mIsCameraConnected.set(connected);
    }

    // 检查摄像头是否连接
    private boolean isCameraConnected() {
        return mIsCameraConnected.get();
    }

    // 设置是否第一次调用
    private void setFirstCall(boolean isSend) {
        isFirstCall.set(isSend);
    }

    // 检查是否第一次调用
    private boolean isFirstCall() {
        return isFirstCall.get();
    }

    //1. 初始化usb camera状态监测
    public void initCameraHelper(Context context) {
        if (DEBUG) Log.d(TAG, "initCameraHelper:");
        mContext = context;
        if (!isCameraConnected()) clearCameraHelper();
        if (mCameraHelper == null) {
            mCameraHelper = new CameraHelper();
            mCameraHelper.setStateCallback(mStateListener);
        }
    }

    // 2. 关闭相机后再次开启相机
    // resume执行
    public void reOpenCamera() {
        if (isFirstCall()) {
            setFirstCall(false);
            return;
        }
        if (mCameraHelper != null && !mCameraHelper.isCameraOpened() && mUsbDevice != null) {
            if (DEBUG)
                Log.d(TAG, "reopenCamera: " + mUsbDevice.getDeviceName() + mCameraHelper.isCameraOpened());
            selectDevice(mUsbDevice);
        }
    }

    //3. 关闭相机
    // onpause执行
    public void closeCamera() {
        if (mCameraHelper != null && mCameraHelper.isCameraOpened()) {
            if (DEBUG)
                Log.d(TAG, "closeCamera: " + mUsbDevice.getDeviceName() + mCameraHelper.isCameraOpened());
            mCameraHelper.stopPreview();
            mCameraHelper.closeCamera();
        }
    }

    //4. 销毁相机
    // ondestroy执行
    public void destoryCamera() {
        if (mCameraHelper != null && mCameraHelper.isCameraOpened() && mUsbDevice != null) {
            if (DEBUG)
                Log.d(TAG, "destoryCamera: " + mUsbDevice.getDeviceName() + mCameraHelper.isCameraOpened());
            closeCamera();
        }
        clearCameraHelper();
        clearAllCallback();
        // 正常关闭线程池
        if (!executorService.isShutdown())
            executorService.shutdown();
    }

    //5. 获取实时视频流，通过控制回调函数
    public void registerCallback(IUsbCamera callback) {
        if (callback != null && !mCallbacks.contains(callback)) {
            mCallbacks.add(callback);
            if (DEBUG) Log.d(TAG, "registerCallback: ");
        }
    }

    public void removeCallback(IUsbCamera callback) {
        mCallbacks.remove(callback);
        if (DEBUG) Log.d(TAG, "removeCallback: ");
    }

    //6. 查看相机是否开启
    public boolean isCameraOpen() {
        if (mCameraHelper != null && mUsbDevice != null && isCameraConnected()) {
            return true;
        } else {
            reOpenCamera();
            return false;
        }
    }
}
